package hotel.switchs.oversea.online.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * springboot创建异步线程配置类
 * @author qyy
 */
@Slf4j
@Configuration
@EnableAsync
public class ThreadAsyncConfig implements AsyncConfigurer {

    @Bean
    public Executor getAsyncExecutor() {

        // return Executors.newFixedThreadPool(100);
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        //设置核心线程数
        threadPool.setCorePoolSize(50);
        //设置最大线程数
        threadPool.setMaxPoolSize(500);
        //线程池所使用的缓冲队列
        threadPool.setQueueCapacity(800);
        //等待任务在关机时完成--表明等待所有线程执行完
        threadPool.setWaitForTasksToCompleteOnShutdown(true);
        // 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
        threadPool.setAwaitTerminationSeconds(60 * 30);
        //  线程名称前缀
        threadPool.setThreadNamePrefix("HhbSwitAsync-");
        // 线程池对拒绝任务(无线程可用)的处理策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃.
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程
        threadPool.initialize();
        return threadPool;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }

    /**
     * 处理异步方法中未捕获的异常
     */
    class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            log.error("HhbSwitAsync Exception message - " + throwable.getMessage());
            log.error("HhbSwitAsync Method name - " + method.getName());
            log.error("HhbSwitAsync Parameter values - " + Arrays.toString(obj));
            // do something...
            //sendMailToAdmin(throwable.getMessage());
        }
    }

}
